/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.andromeda.saturno.property;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * Representa el cursor de cambios aplicados a una propiedad.
 * @author Dickinson Román Arismendy Torres
 */
class StateCursor<T> {

    /**
     * Almacena la lista de cambios a aplicar.
     */
    private List<PropertyChange<T>> changeList = new ArrayList<PropertyChange<T>>();
    private int cursor;

    /**
     * Agrega un cambio a la lista de cambios.
     * @param change el cambio a aplicar.
     */
    public void addChange(PropertyChange<T> change) {
        //Eliminamos los cambios posteriores si los hay
        changeList = changeList.subList(0, cursor);

        if (change != null) {
            changeList.add(change);
            cursor++;
        }
    }

    /**
     * Mueve el cursor de cambios hacia atrás .
     * @return true, si se pudo deshacer un cambio.
     */
    public boolean undo() {
        if (canUndo()) {
            cursor--;
            return true;
        }
        return false;
    }

    /**
     * Mueve el cursor de cambios adelante.
     * @return true, si se pudo realizar algún cambio.
     */
    public boolean redo() {
        if (canRedo()) {
            cursor++;
            return true;
        }
        return false;
    }

    /**
     * Mueve el antes de el primer cambio.
     */
    public boolean undoAll() {
        if (cursor > -1) {
            cursor = -1;
            return true;
        }
        return false;
    }

    /**
     * Mueve al ultimo cambio.
     */
    public boolean redoAll() {
        int size = changeList.size();
        if (cursor != size) {
            cursor = size;
            return true;
        }
        return false;
    }

    /**
     * Verifica si el cursor está en posición de deshacer un cambio.
     * @return true si se puede hacer un cambio.
     */
    public boolean canUndo() {
        return cursor > -1;
    }

    /**
     * Verifica si se puede rehacer un cambio.
     * @return 
     */
    public boolean canRedo() {
        return !changeList.isEmpty() && cursor < changeList.size();
    }

    /**
     * @return Los cambios a realizar desde el primero hasta el cursor.
     */
    public List<PropertyChange<T>> getChanges() {
        if (cursor < 0) {
            return Collections.EMPTY_LIST;
        }
        return changeList.subList(0, cursor);
    }
}
